/**
 * Copyright 2016 vip.com.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 * </p>
 **/

package spring.cloud.tasks.api.controller;


import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import spring.cloud.tasks.api.service.RestApiService;
import spring.cloud.tasks.api.vo.AlarmInfo;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * RESTful APIs for alarm handling.
 * <p>
 * Created by jeff zhu on 10/05/2017.
 */
@Controller
@RequestMapping("/rest/v1/{namespace}/alarms")
public class AlarmRestApiController {

    public static final String ALARM_TYPE = "SATURN.JOB.EXCEPTION";

    private static final String ALARM_TITLE_EXECUTOR_RESTART = "Executor_Restart";

    private static final String ALARM_NAME_EXECUTOR_RESTART = "Saturn Event";

    private static final String ALARM_RAISED_ON_EXECUTOR_RESTART = "ALARM_RAISED_ON_EXECUTOR_RESTART";

    private static final Logger logger = LoggerFactory.getLogger(AlarmRestApiController.class);

    @Resource
    private RestApiService restApiService;


    //@Audit(type = AuditType.REST)
    @RequestMapping(value = "/raise", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ResponseEntity<Object> raise(@PathVariable("namespace") String namespace,
                                        @RequestBody Map<String, Object> reqParams, HttpServletRequest request) throws RuntimeException {
        try {
            String taskId = (String) reqParams.get("taskId");
            String executorId = (String) reqParams.get("executorName");
            Integer taskItemIndex = (Integer) reqParams.get("shardItem");

            AlarmInfo alarmInfo = constructAlarmInfo(reqParams);

            logger.info("try to raise alarm: {}, job: {}, executor: {}, item: {}", alarmInfo, taskId, executorId, taskItemIndex);

            // (since 2.1.4) 如果alarm title是Executor_Restart，而且系统配置ALARM_RAISED_ON_EXECUTOR_RESTART=false, 只记录日志不发送告警
            boolean isExecutorRestartAlarmEvent = isExecutorRestartAlarmEvent(alarmInfo);
            if (isExecutorRestartAlarmEvent) {
                boolean alarmRaisedOnExecutorRestart = false;// systemConfigurationService.getBooleanValue(ALARM_RAISED_ON_EXECUTOR_RESTART, Boolean.FALSE);
                if (!alarmRaisedOnExecutorRestart) {
                    logger.warn(alarmInfo.getMessage());
                } else {
                    restApiService.raiseExecutorRestartAlarm(namespace, executorId, alarmInfo);
                }
            } else {
                if (StringUtils.isBlank(taskId)) {
                    throw new RuntimeException(HttpStatus.BAD_REQUEST.value() + "Invalid request. Missing parameter: taskId");
                }
                restApiService.raiseAlarm(namespace, taskId, executorId, taskItemIndex, alarmInfo);
            }

            return new ResponseEntity<>(HttpStatus.CREATED);
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(HttpStatus.INTERNAL_SERVER_ERROR.value() + e.getMessage(), e);
        }
    }

    private boolean isExecutorRestartAlarmEvent(AlarmInfo alarmInfo) {
        return ALARM_TITLE_EXECUTOR_RESTART.equals(alarmInfo.getTitle()) && ALARM_NAME_EXECUTOR_RESTART.equals(alarmInfo.getName());
    }

    private AlarmInfo constructAlarmInfo(Map<String, Object> reqParams) throws RuntimeException {
        AlarmInfo alarmInfo = new AlarmInfo();
        String level = (String) reqParams.get("level");
        alarmInfo.setLevel(level);

        alarmInfo.setType(ALARM_TYPE);

        String name = (String) reqParams.get("name");
        alarmInfo.setName(name);

        String title = (String) reqParams.get("title");
        alarmInfo.setTitle(title);

        String message = (String) reqParams.get("message");
        if (StringUtils.isNotBlank(message)) {
            alarmInfo.setMessage(message);
        }

        Map<String, String> customFields = (Map<String, String>) reqParams.get("additionalInfo");
        if (customFields != null) {
            alarmInfo.getCustomFields().putAll(customFields);
        }

        return alarmInfo;
    }

}
